<template>
  <div class="app-container">
    <div
      ref="rollBoxContainer"
      class="main-container"
      @mousewheel.prevent="rollingMainWindow"
      @mousedown="handleStartMove"
      @mousemove="handleMovingZoomElement"
      :style="`height:${height}px;`"
    >
      <div ref="zoomElement" :style="mainRollingStyle" class="zoom-element" :draggable="false">
        <slot></slot>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    height: {
      type: [Number, String],
      default: '100%',
    },
  },
  data() {
    return {
      rollBoxContainer: null,
      zoomElement: null,
      redBox: null,
      mainCurScale: 1,
      mousePosition: { x: 0, y: 0 },
      calcMousePosition: { x: 0, y: 0 },
      startMove: false,
    }
  },
  computed: {
    zoomElementValue() {
      return this.zoomElement
    },
    rollBoxContainerValue() {
      return this.rollBoxContainer
    },
    mainRollingStyle() {
      return {
        transformOrigin: `${this.mousePosition.x}px ${this.mousePosition.y}px`,
        transform: `scale(${this.mainCurScale})`,
        cursor: this.mainCurScale > 0.5 ? 'grab' : '',
      }
    },
  },
  mounted() {
    this.zoomElement = this.$refs.zoomElement
    this.rollBoxContainer = this.$refs.rollBoxContainer
    window.addEventListener('mouseup', () => {
      this.startMove = false
    })
  },
  methods: {
    handleStartMove() {
      this.startMove = true
    },
    getRect(el) {
      if (el) return el && el.getBoundingClientRect()
      else return {}
    },

    // 滚动大图
    rollingMainWindow(e) {
      const { clientX, clientY } = e
      const delta = Math.sign(e.deltaY)
      this.mainCurScale -= delta * 0.1
      this.mainCurScale = Math.max(this.mainCurScale, 0.5)

      const rollBoxRect = this.getRect(this.rollBoxContainer)
      const { left, top, width, height } = this.getRect(this.zoomElement)

      this.mousePosition.x = ((clientX - left) / width) * rollBoxRect.width
      this.mousePosition.y = ((clientY - top) / height) * rollBoxRect.height
      this.synchronizeMoveRedBox()
    },
    synchronizeMoveRedBox() {
      const rollBoxRect = this.getRect(this.rollBoxContainer)
      const { width, height } = this.getRect(this.smallWindow)
      this.calcMousePosition.x = (this.mousePosition.x / rollBoxRect.width) * width
      this.calcMousePosition.y = (this.mousePosition.y / rollBoxRect.height) * height
    },
    handleMovingZoomElement(e) {
      if (!this.startMove) {
        return
      }

      const scale = this.mainCurScale
      const { movementX, movementY } = e
      if (this.mainCurScale < 1) {
        this.mousePosition.x += movementX / scale
        this.mousePosition.y += movementY / scale
      } else {
        this.mousePosition.x -= movementX / scale
        this.mousePosition.y -= movementY / scale
      }
      this.mousePosition = { ...this.mousePosition }
      this.synchronizeMoveRedBox()
    },
  },
}
</script>
<style lang='less' scoped>
.app-container {
  user-select: none;
  -webkit-user-drag: none;

  .main-container {
    width: 100%;
    height: calc(100vh - 260px);
    position: relative;
    border: 1px solid #fff;
    overflow: hidden;

    .zoom-element {
      height: 100%;
      width: 100%;
    }

    .small-window {
      height: 30%;
      width: 30%;
      position: absolute;
      right: -1px;
      bottom: -1px;
      border: 1px solid #fff;

      .red-box-container {
        height: 100%;
        width: 100%;
        background-image: url(http://surl.li/dpeat);
        background-size: 100%;

        .red-box {
          height: 100%;
          width: 100%;
          cursor: grab;
        }
      }
    }
  }
}
</style>
 